﻿using ADRcpLib;
using ADSioLib;
using VirtualWall.Models;
using log4net;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VirtualWall.Machines
{
    /// <summary>
    /// 读卡器
    /// 汪虎 2022-12-07
    /// </summary>
    public class Rcp
    {
        private static readonly ILog log = LogManager.GetLogger("Rcp");

        //远程读卡器串口 新版
        public  SioBase SioBase = new SioNet();
        public  RcpBase RcpBase = new RcpBase();

        /// <summary>
        /// 进出口类型
        /// </summary>
        public CameraType ChannelType { get; set; }

        /// <summary>
        /// 附属相机对象
        /// </summary>
        public Camera AttachedCamera = null;

        public int _Number = 0;
        /// <summary>
        /// 相机编号、索引
        /// </summary>
        public int Number
        {
            get
            {
                return _Number;
            }
        }

        /// <summary>
        /// 当前读卡器的IP
        /// </summary>
        public string IP { get; set; }

        public bool IsConnected
        {
            get
            {
                if (SioBase == null) return false;
                if (!SioBase.bConnected) return false;
                return true;
            }
        }

        public Rcp(CameraType channelType, int number, Camera camear,string ip, int port=49152)
        {
            IP = ip;
            _Number = number;
            ChannelType = channelType;
            AttachedCamera = camear;
            InitSioBase(ip, port);
        }

        /// <summary>
        /// 初始化加载高频读头
        /// </summary>
        private void InitSioBase(string ip,int port)
        {
            try
            {
                SioBase.onStatus += SioBase_onStatus;
                SioBase.onReceived += SioBase_onReceived;
                RcpBase.RxRspParsed += RcpBase_RxRspParsed;
                if (!string.IsNullOrWhiteSpace(ip))
                {
                    SioBase.Connect(ip, port);
                }
            }
            catch (Exception e)
            {
                log.Error($"InitSioBase Failed!{e.Message}");
            }

        }
        #region 高频设备的回调函数


        public void SendSio(ProtocolPacket protocolPacket)
        {
            if (IsConnected)
            {
                RcpBase.ShowBytePack(protocolPacket);
                SioBase.Send(protocolPacket.ToArray());
            }
        }

        private void SioBase_onStatus(object sender, StatusEventArgs e)
        {
            try
            {
                switch ((StatusType)e.Status)
                {
                    case StatusType.CONNECT_OK:
                        try
                        {
                            int intVer = Convert.ToInt32(e.Msg);
                        }
                        catch { }
                        log.Info("CONNECTED OK> " + e.Msg + "(" + SioBase.ToString() + ")");
                        break;
                    case StatusType.CONNECT_FAIL:
                        log.Info("ERROR> " + e.Msg + "(" + SioBase.ToString() + ")");
                        break;
                    case StatusType.DISCONNECT_OK:
                        log.Info("DISCONNECT OK> " + e.Msg + "(" + SioBase.ToString() + ")");
                        break;
                    case StatusType.DISCONNECT_EXCEPT:
                        log.Info("ERROR> " + e.Msg + "(" + SioBase.ToString() + ")");
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                log.Info(ex.ToString());
            }
        }

        private void SioBase_onReceived(object sender, ReceivedEventArgs e)
        {
            RcpBase.ReciveBytePkt(e.Data);
        }

        private void RcpBase_RxRspParsed(object sender, ProtocolEventArgs e)
        {
            try
            {
                log.Info("Rx> " + TagInfo.ByteArrayToHexString(e.Data));
                ParseRsp(e.Protocol);
            }
            catch (Exception ex)
            {
                log.Info(ex.ToString());
            }
        }


        private int GetCodelen(byte iData)
        {
            return (((iData >> 3) + 1) * 2);
        }

        private string GetRssi(byte rssi)
        {
            int rssidBm = (sbyte)rssi; // rssidBm is negative && in bytes
            rssidBm -= Convert.ToInt32("-20", 10);
            rssidBm -= Convert.ToInt32("3", 10);
            return rssidBm.ToString();
        }

        private void ParseRsp(ProtocolPacket protocolPacket)
        {
            switch (protocolPacket.Code)
            {
                case RcpBase.RCP_CMD_INFO:
                    if (protocolPacket.Length > 30 && (protocolPacket.Type & 0x7f) == 0)
                    {
                        #region Parameter
                        string strInfo = Encoding.ASCII.GetString(protocolPacket.Payload, 0, protocolPacket.Length);
                        log.Info("Type:" + RcpBase.Mode + RcpBase.Type + " - Version:" + RcpBase.Version + " - Address: " + RcpBase.Address);
                        #endregion
                    }
                    break;

                case RcpBase.RCP_MM_READ_C_UII:
                    if (protocolPacket.Type == 2 || protocolPacket.Type == 5)
                    {
                        int pcepclen = GetCodelen(protocolPacket.Payload[1]);
                        int datalen = protocolPacket.Length - 2;//去掉天线号去掉rssi
                        TagInfo cp = new TagInfo
                        {
                            TagType = TagType.TYPE_6C,
                            Length = datalen,//去掉天线号去掉RSSI
                            Antenna = protocolPacket.Payload[0],
                            PCData = TagInfo.GetData(protocolPacket.Payload, 1, 2),
                            EPCData = TagInfo.GetData(protocolPacket.Payload, 3, pcepclen - 2),
                            Rssi = GetRssi(protocolPacket.Payload[protocolPacket.Length - 1]) + "dBm"
                        };
                        if ((datalen - pcepclen) > 0) cp.DataBytes = TagInfo.GetData(protocolPacket.Payload, 1 + pcepclen, datalen - pcepclen);

                        CarLabelModel carLabel = SQLDataAccess.LoadCarLabel(cp.EPCString);
                        if (carLabel != null)
                        {
                            if (carLabel.PlateNo != AttachedCamera.PlateNo)
                            {
                                if(ChannelType== CameraType.入口)
                                {
                                    //车辆进场要执行的动作
                                    AttachedCamera.GoIn(AttachedCamera.Handle, AttachedCamera.PlateNo);
                                }
                                else
                                {
                                    //车辆进场要执行的动作
                                    AttachedCamera.GoOut(AttachedCamera.Handle, AttachedCamera.PlateNo);
                                }
                                log.Info("读卡器," + cp.EPCString + "," + carLabel.PlateNo);
                            }
                        }
                        else
                        {
                            log.Info("卡号: " + cp.EPCString + " 未查询到车号");
                        }
                    }

                    break;
                case RcpBase.RCP_MM_READ_C_DT:
                    if (protocolPacket.Type == 0)
                    {
                        int pcepclen = GetCodelen(protocolPacket.Payload[1]);
                        int datalen = protocolPacket.Length - pcepclen - 1;//去掉天线号去掉PC+EPc
                        TagInfo cp = new TagInfo
                        {
                            TagType = TagType.TYPE_6C,
                            Length = datalen,
                            Antenna = protocolPacket.Payload[0],
                            PCData = TagInfo.GetData(protocolPacket.Payload, 1, 2),
                            EPCData = TagInfo.GetData(protocolPacket.Payload, 3, pcepclen - 2),
                            DataBytes = TagInfo.GetData(protocolPacket.Payload, 1 + pcepclen, datalen)
                        };
                    }
                    break;
                case RcpBase.RCP_MM_WRITE_C_DT:
                    if (protocolPacket.Type == 0)
                    {
                        int pcepclen = GetCodelen(protocolPacket.Payload[1]);
                        int datalen = protocolPacket.Length - pcepclen - 1;//去掉天线号去掉PC+EPc
                        TagInfo cp = new TagInfo
                        {
                            TagType = TagType.TYPE_6C,
                            Length = datalen,
                            Antenna = protocolPacket.Payload[0],
                            PCData = TagInfo.GetData(protocolPacket.Payload, 1, 2),
                            EPCData = TagInfo.GetData(protocolPacket.Payload, 3, pcepclen - 2)
                        };
                    }
                    break;
                case RcpBase.RCP_MM_GET_ACCESS_EPC_MATCH:
                    break;
                case RcpBase.RCP_MM_SET_ACCESS_EPC_MATCH:
                    break;
                default:
                    break;
            }
        }

     
        #endregion
    }
}
